package com.siyoumi.app.modules.app_book.service;

import com.siyoumi.app.entity.BookSku;
import com.siyoumi.app.entity.BookSkuDay;
import com.siyoumi.app.entity.BookSpu;
import com.siyoumi.app.entity.BookSpuDay;
import com.siyoumi.app.modules.app_book.vo.*;
import com.siyoumi.app.service.BookSkuDayService;
import com.siyoumi.app.service.BookSkuService;
import com.siyoumi.component.XApp;
import com.siyoumi.component.XSpringContext;
import com.siyoumi.component.http.InputData;
import com.siyoumi.component.http.XHttpContext;
import com.siyoumi.exception.EnumSys;
import com.siyoumi.mybatispuls.JoinWrapperPlus;
import com.siyoumi.service.IWebService;
import com.siyoumi.util.XDate;
import com.siyoumi.util.XReturn;
import com.siyoumi.util.XStr;
import com.siyoumi.validator.XValidator;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

//
@Slf4j
@Service
public class SvcBookSku
        implements IWebService {
    static public SvcBookSku getBean() {
        return XSpringContext.getBean(SvcBookSku.class);
    }

    static public BookSkuService getApp() {
        return BookSkuService.getBean();
    }

    /**
     * 根据天数获取sku 金额
     *
     * @param spuId
     * @param day
     */
    public BookSku getEntitySku(String spuId, Integer day) {
        String key = XStr.format("sku_list|{0}", spuId);
        List<BookSku> listSku = XHttpContext.getAndSetData(key, k -> {
            //spu 全部上架sku，日期从小到大排序
            JoinWrapperPlus<BookSku> query = listQuery(spuId);
            query.eq("bsku_enable", 1);
            query.orderByDesc("bsku_day");
            return getApp().get(query);
        });

        if (listSku.isEmpty()) {
            return null;
        }

        BookSku entitySku = listSku.stream().filter(item -> item.getBsku_day() <= day).findFirst().orElse(null);
        if (entitySku == null) {
            //输入的日期大于所有配置的sku，拿最后一个
            //1,5,15,30 当输入日期大于30 直接拿30价格
            entitySku = listSku.get(listSku.size() - 1);
        }

        return entitySku;
    }

    public List<Map<String, Object>> getList(List<String> spuIds) {
        String[] select = {
                "bsku_id",
                "bsku_day",
                "bsku_spu_id",
                "bsku_day_price",
                "bsku_day_price_private",
        };
        JoinWrapperPlus<BookSku> query = listQuery(spuIds);
        query.eq("bsku_enable", 1);
        query.orderByDesc("bsku_day");
        query.select(select);

        return getApp().getMaps(query);
    }

    public JoinWrapperPlus<BookSku> listQuery(String spuId) {
        return listQuery(List.of(spuId));
    }

    public JoinWrapperPlus<BookSku> listQuery(List<String> spuIds) {
        JoinWrapperPlus<BookSku> query = listQuery();
        query.in("bsku_spu_id", spuIds);
        return query;
    }

    public JoinWrapperPlus<BookSku> listQuery() {
        return listQuery(InputData.getIns());
    }

    /**
     * select
     *
     * @return query
     */
    public JoinWrapperPlus<BookSku> listQuery(InputData inputData) {
        String spuId = inputData.input("spu_id");
        String id = inputData.input("id");

        JoinWrapperPlus<BookSku> query = getApp().join();
        query.eq("bsku_x_id", XHttpContext.getX())
                .eq("bsku_del", 0);
        if (XStr.hasAnyText(id)) {
            query.eq("bsku_id", id);
        } else {
            if (XStr.hasAnyText(spuId)) { //spu_id
                query.eq("bsku_spu_id", spuId);
            }
        }

        return query;
    }

    public List<BookSkuDay> listDay(String skuId, LocalDateTime dateBegin, LocalDateTime dateEnd) {
        String key = skuId + XStr.md5(XDate.toDateString(dateBegin) + XDate.toDateString(dateEnd));
        return XHttpContext.getAndSetData(key, k -> {
            JoinWrapperPlus<BookSkuDay> query = listDayQuery(skuId);
            query.between("bskud_date", dateBegin, dateEnd);

            return BookSkuDayService.getBean().get(query);
        });
    }

    public List<SkuDayData> listDay(BookSku entitySku, LocalDateTime dateBegin, LocalDateTime dateEnd) {
        List<BookSkuDay> listDay = listDay(entitySku.getKey(), dateBegin, dateEnd);
        List<LocalDateTime> dates = XDate.getDateList(dateBegin, dateEnd, null);
        List<SkuDayData> list = new ArrayList<>();
        for (LocalDateTime date : dates) {
            BookSkuDay entity = listDay.stream().filter(item -> item.getBskud_date().equals(date)).findFirst()
                    .orElse(null);
            if (entity == null) { //没有配置拿默认
                entity = new BookSkuDay();
                entity.setBskud_day_price(entitySku.getBsku_day_price());
                entity.setBskud_day_price_private(entitySku.getBsku_day_price_private());
            }

            SkuDayData item = new SkuDayData();
            item.setDate(date);
            item.setDay_price(entity.getBskud_day_price());
            item.setDay_price_private(entity.getBskud_day_price_private());
            //计算加价部分
            if (item.getDay_price().compareTo(entitySku.getBsku_day_price()) > 0) {
                item.setDay_price_add(item.getDay_price().subtract(entitySku.getBsku_day_price()));
                item.setDay_price(entitySku.getBsku_day_price());
            }
            if (item.getDay_price_private().compareTo(entitySku.getBsku_day_price_private()) > 0) {
                item.setDay_price_private_add(item.getDay_price_private().subtract(entitySku.getBsku_day_price_private()));
                item.setDay_price_private(entitySku.getBsku_day_price_private());
            }

            list.add(item);
        }

        return list;
    }

    /**
     * 每日库存
     *
     * @return query
     */
    public JoinWrapperPlus<BookSkuDay> listDayQuery(String skuId) {
        JoinWrapperPlus<BookSkuDay> query = BookSkuDayService.getBean().join();
        query.eq("bskud_x_id", XHttpContext.getX())
                .eq("bskud_sku_id", skuId);

        return query;
    }

    public XReturn validCommon(BookSku entity) {
        if (entity == null) {
            return EnumSys.ERR_VAL.getR("sku_id异常");
        }
        if (entity.getBsku_del() != 0) {
            return EnumSys.ERR_VAL.getR("sku不存在");
        }
        return EnumSys.OK.getR();
    }

    /**
     * 能否编辑
     *
     * @param entity
     */
    public XReturn canEdit(BookSku entity) {
        XReturn r = validCommon(entity);
        if (r.err()) {
            return r;
        }

        if (entity.getBsku_enable() == 1) {
            return EnumSys.ERR_VAL.getR(entity.skuName() + "：上架中");
        }

        return EnumSys.OK.getR();
    }

    /**
     * 批量修改日期库存
     *
     * @param vo
     */
    public XReturn dayEditBatch(VaBookSkuDay vo) {
        BookSku entitySku = getApp().getEntityLock(vo.getBskud_sku_id());
        XValidator.err(canEdit(entitySku));

        //日期更新库存和加价
        List<LocalDateTime> dateList = XDate.getDateList(vo.getBegin_date(), vo.getEnd_date(), vo.getWeek());
        List<BookSkuDay> listDay = listDay(vo.getBskud_sku_id(), vo.getBegin_date(), vo.getEnd_date());
        for (LocalDateTime date : dateList) {
            BookSkuDay entity = listDay.stream().filter(item -> item.getBskud_date().equals(date)).findFirst().orElse(null);

            BookSkuDay entityUpdate = new BookSkuDay();
            if (entity == null) {
                entityUpdate.setAutoID();
                entityUpdate.setBskud_spu_id(entitySku.getBsku_spu_id());
                entityUpdate.setBskud_sku_id(entitySku.getKey());
                entityUpdate.setBskud_x_id(entitySku.getBsku_x_id());
                entityUpdate.setBskud_date(date);
            }
            entityUpdate.setBskud_day_price(vo.getBspud_add_price());
            entityUpdate.setBskud_day_price_private(vo.getBspud_add_price_private());
            BookSkuDayService.getBean().saveOrUpdatePassEqualField(entity, entityUpdate);
        }

        return EnumSys.OK.getR();
    }

    public XReturn save(InputData inputData, VaBookSku vo) {
        List<String> ignoreField = new ArrayList<>();
        if (inputData.isAdminEdit()) {
            ignoreField.add("bsku_spu_id");
        }

        return XApp.getTransaction().execute(status -> {
            XReturn r = getApp().saveEntity(inputData, vo, true, ignoreField);
            return r;
        });
    }

    /**
     * 删除
     */
    @SneakyThrows
    @Transactional(propagation = Propagation.MANDATORY)
    public XReturn delete(List<String> ids) {
        XReturn r = XReturn.getR(0);

        JoinWrapperPlus<BookSku> query = listQuery();
        query.in(BookSku.tableKey(), ids);
        List<BookSku> list = getApp().get(query);
        for (BookSku entity : list) {
            if (entity.getBsku_enable() == 1) {
                return XReturn.getR(20108, entity.getBsku_day() + "晚，已上架不能删除");
            }
        }

        getApp().delete(ids);

        return r;
    }


    /**
     * 审核
     *
     * @param vo
     */
    @Transactional(rollbackFor = Exception.class)
    public XReturn audit(VoBookSkuAudit vo) {
        List<BookSku> list = getApp().get(vo.getIds());
        if (list.isEmpty()) {
            return EnumSys.OK.getR();
        }
        //检查上下架
        BookSpu entitySpu = SvcBookSpu.getApp().loadEntity(list.get(0).getBsku_spu_id());
        XValidator.err(SvcBookSpu.getBean().canEdit(entitySpu));

        for (BookSku entity : list) {
            if (Objects.equals(entity.getBsku_enable(), vo.getEnable())) {
                continue;
            }
            //
            XValidator.err(validCommon(entity));
            //
            if (vo.getEnable() == 1) {
                if (entity.getBsku_day_price().compareTo(BigDecimal.ZERO) <= 0) {
                    XValidator.err(EnumSys.ERR_VAL.getR(entity.skuName() + "：拼房价为0，无法操作"));
                }
                if (entity.getBsku_day_price_private().compareTo(BigDecimal.ZERO) <= 0) {
                    XValidator.err(EnumSys.ERR_VAL.getR(entity.skuName() + "：包房价为0，无法操作"));
                }
                if (entity.getBsku_day_price_private().compareTo(entity.getBsku_day_price()) < 0) {
                    XValidator.err(EnumSys.ERR_VAL.getR(entity.skuName() + "：包房价 < 拼房价，无法操作"));
                }
            }

            BookSku entityUpdate = new BookSku();
            entityUpdate.setBsku_id(entity.getKey());
            entityUpdate.setBsku_enable(vo.getEnable());
            getApp().updateById(entityUpdate);
        }
        return EnumSys.OK.getR();
    }
}
